package utils;

import com.google.gson.*;
import play.Logger;
import play.data.binding.Binder;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
 * JSON的实用类
 */
public class JsonUtils {

    private static GsonBuilder gsonBuilder;
    static {
        gsonBuilder = new GsonBuilder();
        gsonBuilder.setDateFormat("'ISO8601:'yyyy-MM-dd'T'HH:mm:ssZ");
    }
    /**
     * 转换为JSON树
     * @param data
     * @return
     */
    public static JsonElement toJsonTree(Object data){
        return gsonBuilder.create().toJsonTree(data);
    }

    /**
     * 解析为JSON元素对象
     * @param data
     * @return
     */
    public static JsonObject parse(String data) {
        JsonObject ret;
        try {
            ret = (new JsonParser()).parse(data).getAsJsonObject();
        } catch (Exception e) {
            return null;
        }
        return ret;
    }

    /**
     * 从JSON对象里创建对象
     * @param cl
     * @param data
     * @param <T>
     * @return
     */
    @SuppressWarnings("unchecked")
    public static<T> T conver(Class<T> cl, JsonElement data){
        Object converObj = converToObject(cl, data);
        if(converObj != null){
            try{
                return (T)converObj;
            }catch (ClassCastException ex){
                return null;
            }
        }else{
            return null;
        }
    }
    /**
     * 从JSON对象里创建对象
     * @param cl
     * @param data
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object converToObject(Class<?> cl, JsonElement data){
        if (data.isJsonNull()) {
            return null;
        }
        try{
            if(data.isJsonObject()){
                return converToObject(cl, data.getAsJsonObject());
            }else if(data.isJsonArray()){
                JsonArray jsonArray = data.getAsJsonArray();
                List<Object> objects = new ArrayList<Object>(jsonArray.size());
                for(JsonElement el : jsonArray){
                    Object value = converToObject(cl, el);
                    objects.add(value);
                }
                return objects;
            }else{
                return Binder.directBind(data.getAsString(), cl);
            }
        }catch (Exception ex){
            return null;
        }
    }

    /**
     * 从JSON数据里创建对应的对象
     * @param cl
     * @param data
     * @return
     */
    public static Object converToObject(Class<?> cl, JsonObject data){
        try{
            List<Field> fields = new ArrayList<Field>(12);
            Class<?> classType = cl;
            while(classType != null && classType != Object.class){
                Field[] allFields = classType.getDeclaredFields();
                Collections.addAll(fields, allFields);
                if(classType.isInterface()) break;
                classType = classType.getSuperclass(); //继续处理父级类
            }

            Object obj = cl.newInstance();
            for(Field field : fields){
                field.setAccessible(true);
                if(data.has(field.getName())){
                    JsonElement element = data.get(field.getName());
                    Class<?> type = field.getType();
                    if(field.getGenericType() != type){
                        Type genericType = field.getGenericType();
                        if(genericType instanceof ParameterizedType){
                            Type[] types = ((ParameterizedType)genericType).getActualTypeArguments();
                            if(types.length > 0){
                                type = (Class<?>) types[0];
                            }
                        }
                    }
                    if(element.isJsonNull()){
                        field.set(obj, null);
                    }else if(element.isJsonArray()){
                        JsonArray jsonArray = element.getAsJsonArray();
                        List<Object> objects = new ArrayList<Object>(jsonArray.size());
                        for(JsonElement el : jsonArray){
                            Object value = converToObject(type, el);
                            objects.add(value);
                        }
                        field.set(obj, objects);
                    }else if(element.isJsonObject()){
                        Object value = converToObject(type, element.getAsJsonObject());
                        field.set(obj, value);
                    }else{
                        try{
                            Object value = Binder.directBind(data.get(field.getName()).getAsString(), field.getType());
                            field.set(obj, value);
                        }catch (Exception ex){

                        }
                    }
                }
            }
            return obj;
        }catch (Exception ex){
            return null;
        }
    }
    /**
     * 获取JSON对象里的Int
     * @param jsonObject
     * @param name
     * @return
     */
    public static Integer getInteger(JsonObject jsonObject, String name){
        if(jsonObject.has(name)){
            JsonElement jsonElement = jsonObject.get(name);
            if(jsonElement.isJsonNull()){
                return 0;
            }
            return jsonElement.getAsInt();
        }else {
            return 0;
        }
    }
    /**
     * 获取JSON对象里的LONG
     * @param jsonObject
     * @param name
     * @return
     */
    public static Long getLong(JsonObject jsonObject, String name){
        if(jsonObject.has(name)){
            JsonElement jsonElement = jsonObject.get(name);
            if(jsonElement.isJsonNull()) {
                return null;
            }
            return jsonElement.getAsLong();
        }else {
            return null;
        }
    }
    /**
     * 获取JSON对象里的字符串
     * @param jsonObject
     * @param name
     * @return
     */
    public static String getString(JsonObject jsonObject, String name){
        if(jsonObject.has(name)){
            JsonElement jsonElement = jsonObject.get(name);
            if(jsonElement.isJsonNull()) {
                return null;
            }

            return jsonElement.getAsString();
        }else {
            return null;
        }
    }

    /**
     * json 转 string
     * @param json
     * @return
     */
    public static String formatJson(Object json) {
        Gson parser = new Gson();
        String jsonString = parser.toJson(json);
        return jsonString;
    }


    /**
     * jsonArray转list<jsonObject>
     * @param jsonArray
     * @return
     */
    public static List<JsonObject> convertJsonArray(JsonArray jsonArray){
        List<JsonObject> jsonObjects = new ArrayList<JsonObject>();
        for (int index = 0 ; index < jsonArray.size() ; index ++){
            jsonObjects.add(jsonArray.get(index).getAsJsonObject());
        }
        return jsonObjects;
    }

    /******************队列json数据转换************************/
    /**
     * 把字符串转换为 json 对象
     *
     * @param str
     * @return
     */
    public static JsonObject string2Json(String str) {
        JsonObject jsonObject = null;

        try {
            JsonParser jsonParser = new JsonParser();
            jsonObject = jsonParser.parse(str).getAsJsonObject();
        } catch (Exception e){
            Logger.error("%s : %s", "字符串转换为 json 对象出错", str);
        }

        return jsonObject;
    }

    /**
     * 获取JSON的对象转换JsonArray
     * @param cl
     * @param jsonArray
     * @return
     */
    public static JsonArray converToJsonArray(Class cl,JsonArray jsonArray){
        if (jsonArray== null || jsonArray.size() == 0){
            return null;
        }
        JsonArray array = new JsonArray();
        Gson gson = new Gson();
        for (JsonElement element:jsonArray){
             array.add(new Gson().toJsonTree(gson.fromJson(element,cl)));
        }
        return array;
    }

    public static JsonArray string2JsonArray(String arrayStr) {
        JsonArray jsonArray = null;

        try {
            JsonParser jsonParser = new JsonParser();
            jsonArray = jsonParser.parse(arrayStr).getAsJsonArray();
        } catch (Exception e){
            Logger.error("%s : %s", "字符串转换为 jsonArray 对象出错", arrayStr);
        }

        return jsonArray;
    }


    public static void main(String[] args){
        /*String pointList ="[{\"id\":1,\"myCity\":\"广州市\",\"myDistrict\":\"天河区\",\"myStreet\":\"岗顶-公交车站\",\"xPoint\":\"113.34847029446165\",\"yPoint\":\"23.141027791476183\"},{\"id\":2,\"myCity\":\"广州市\",\"myDistrict\":\"天河区\",\"myStreet\":\"学院-公交车站\",\"xPoint\":\"113.3803794536238\",\"yPoint\":\"23.134208791185713\"},{\"id\":3,\"myCity\":\"广州市\",\"myDistrict\":\"海珠区\",\"myStreet\":\"北岛创意园\",\"xPoint\":\"113.41182321866748\",\"yPoint\":\"23.099146996302004\"}]";
        JsonArray jsonArray =string2JsonArray(pointList);
        List<JsonObject> list= convertJsonArray(jsonArray);
        System.out.print(list);*/
    }
}